package com.boot.study.config;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.Configuration;

import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.MasterSlaveDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.keygen.DefaultKeyGenerator;

@ConditionalOnProperty(prefix = "master-slave", name="open", havingValue ="true")
@Configuration
public class DbConfig {

	@Bean
	public DataSource dataSource() {
		Map<String, DataSource> dataSourceMap = new HashMap<>();

		Map<String, DataSource> slaveDataSourceMap0 = new HashMap<>();
		Map<String, DataSource> slaveDataSourceMap1 = new HashMap<>();
		slaveDataSourceMap0.put("db_0_slave", createDataSource("db_0_slave"));
		slaveDataSourceMap1.put("db_1_slave", createDataSource("db_1_slave"));

		try {
			DataSource masterSlave0 = MasterSlaveDataSourceFactory.createDataSource("db_0", "db_0_master",
					createDataSource("db_0"), slaveDataSourceMap0);
			DataSource masterSlave1 = MasterSlaveDataSourceFactory.createDataSource("db_1", "db_1_master",
					createDataSource("db_1"), slaveDataSourceMap1);

			dataSourceMap.put("db_0", masterSlave0);
			dataSourceMap.put("db_1", masterSlave1);
		} catch (SQLException e1) {
			e1.printStackTrace();
		}

		DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);

		TableRule orderTableRule = TableRule.builder("t_order").generateKeyColumn("orderId", DefaultKeyGenerator.class)
				.actualTables(Arrays.asList("t_order_0", "t_order_1", "t_order_2")).dataSourceRule(dataSourceRule)
				.build();

		ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(dataSourceRule)
				.tableRules(Arrays.asList(orderTableRule))
				.databaseShardingStrategy(new DatabaseShardingStrategy("userId", new ModuloDatabaseShardingAlgorithm()))
				.tableShardingStrategy(new TableShardingStrategy("orderId", new ModuloTableShardingAlgorithm()))
				.build();

		try {
			DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);

			return dataSource;
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return null;
	}

	private static DataSource createDataSource(final String dataSourceName) {
		DruidDataSource result = new DruidDataSource();
		result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
		result.setUrl(String.format("jdbc:mysql://localhost:3306/%s", dataSourceName));
		result.setUsername("root");
		result.setPassword("111111");
		return result;
	}
}
